package club.cearnach.api.service.impl;

import club.cearnach.api.annotation.CacheDeleteAll;
import club.cearnach.api.dao.IMovieLanguageDao;
import club.cearnach.entity.MovieLanguage;
import club.cearnach.api.exception.MovieException;
import club.cearnach.api.exception.MovieLanguageException;
import club.cearnach.api.form.PageBean;
import club.cearnach.api.service.IMovieLanguageService;
import club.cearnach.api.service.IMovieService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * @author 阮胜
 * @date 2018/5/12 14:29
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class MovieLanguageServiceImpl implements IMovieLanguageService {
    public static final String CACHE_MOVIE_LANGUAGE_NAME = "CACHE_MOVIE_LANGUAGE_NAME";
    public static final String CACHE_MOVIE_LANGUAGE_FIND_ALL = "CACHE_MOVIE_LANGUAGE_FIND_ALL";
    private final IMovieLanguageDao movieLanguageDao;
    @Autowired
    private IMovieService movieService;

    public MovieLanguageServiceImpl(IMovieLanguageDao movieLanguageDao) {
        this.movieLanguageDao = movieLanguageDao;
    }

    @Override
    public Page<MovieLanguage> findAll(Pageable pageable) {
        return movieLanguageDao.findAll(pageable);
    }

    @CacheDeleteAll
    @Override
    public MovieLanguage save(MovieLanguage movieLanguage) {
        Optional<MovieLanguage> movieLanguageOptional = movieLanguageDao.findByLanguage(movieLanguage.getLanguage());

        return movieLanguageOptional.map(movieLanguageDao::saveAndFlush)
                .orElseGet(() -> movieLanguageDao.saveAndFlush(movieLanguage));
    }

    @Cacheable(value = CACHE_MOVIE_LANGUAGE_NAME, key = "'movie_language_'+#id")
    @Override
    public MovieLanguage findById(Integer id) throws MovieLanguageException {
        return movieLanguageDao.findById(id).orElseThrow(() -> new MovieLanguageException(MovieLanguageException.MOVIE_LANGUAGE_CAN_NOT_FOUND));
    }

    @CacheDeleteAll
    @Override
    public void delete(Integer id) throws MovieLanguageException {
        movieLanguageDao.findById(id).orElseThrow(() -> new MovieLanguageException(MovieLanguageException.MOVIE_LANGUAGE_CAN_NOT_FOUND));
        movieService.findByLanguageId(id).forEach(movie -> {
            try {
                movieService.delete(movie.getId());
            } catch (MovieException e) {
                e.printStackTrace();
            }
        });
        movieLanguageDao.deleteById(id);
    }


    @CacheDeleteAll
    @Override
    public void deleteIn(Integer[] idArr) {
        for (int id : idArr) {
            try {
                delete(id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Cacheable(value = CACHE_MOVIE_LANGUAGE_FIND_ALL, key = "'findAllOrderByCreateDate_'+#pageBean.getPage()+'_'+#pageBean.getSize()")
    @Override
    public Page<MovieLanguage> findAllOrderByCreateDate(PageBean pageBean) {
        return movieLanguageDao.findAll(PageRequest.of(pageBean.getPage(), pageBean.getSize(), Sort.by(Sort.Direction.DESC, "createDate")));
    }

    @Override
    public long count() {
        return movieLanguageDao.count();
    }


    @Override
    public boolean isExist(Integer id, String language) {
        return id == 0
                ? movieLanguageDao.findByLanguage(language).isPresent()
                : movieLanguageDao.findByLanguageAndIdNot(language, id).isPresent();

    }

    @Override
    public boolean isExist(MovieLanguage movieLanguage) {
        return isExist(movieLanguage.getId(), movieLanguage.getLanguage());
    }

    @Override
    public List<MovieLanguage> findAll() {
        return movieLanguageDao.findAll();
    }
}
